package com.yanqu.road.server.manager.banquet;

import com.alibaba.fastjson.JSON;
import com.yanqu.road.entity.DataStatus;
import com.yanqu.road.entity.banquet.BanquetGiftInfo;
import com.yanqu.road.entity.banquet.BanquetInfo;
import com.yanqu.road.entity.banquet.UserBanquetRecord;
import com.yanqu.road.entity.banquet.auto.CrossBanquetAutoData;
import com.yanqu.road.entity.banquet.auto.CrossBanquetAutoJoinLog;
import com.yanqu.road.entity.banquet.cross.CrossBanquetData;
import com.yanqu.road.entity.banquet.cross.CrossBanquetMember;
import com.yanqu.road.entity.banquet.cross.CrossBanquetRecord;
import com.yanqu.road.entity.enums.eBanquetInfoType;
import com.yanqu.road.entity.enums.eBanquetType;
import com.yanqu.road.entity.player.UserBaseInfo;
import com.yanqu.road.entity.servercenter.ServerInfo;
import com.yanqu.road.logic.bussiness.crossbanquet.CrossBanquetBussiness;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.logic.pb.PlayerBasePb;
import com.yanqu.road.logic.thread.ThreadTaskManger;
import com.yanqu.road.message.YanQuMessage;
import com.yanqu.road.pb.banquet.BanquetProto;
import com.yanqu.road.pb.banquet.CrossBanquetProto;
import com.yanqu.road.pb.player.PlayerProto;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.server.logic.MessageHelper;
import com.yanqu.road.server.manager.user.CrossUserMgr;
import com.yanqu.road.server.manger.ServerListMgr;
import com.yanqu.road.server.pb.banquet.CrossBanquetPb;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.GameProtocol;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.ConfigHelper;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.UUIDHelper;
import com.yanqu.road.utils.YanQuMessageUtils;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class CrossBanquetMgr extends TempMgr {

    /**
     * 赴宴记录有效期  30天
     */
    public static long RECORD_EXPIRE_TIME = 30 * DateHelper.DAY_MILLIONS;

    private static Map<String, CrossBanquetData> userCrossBanquetDataMap;

    private static Map<String, Map<Long, CrossBanquetMember>> crossBanquetMemberMap = new ConcurrentHashMap<>();

    //增量同步新加入的成员
    private static Map<String, List<CrossBanquetMember>> crossBanquetMemberSyncMap = new ConcurrentHashMap<>();

    private static Map<String, CrossBanquetRecord> crossBanquetRecordMap;

    private static Map<String, Object> lockMap;

    private static RandomHelper random = new RandomHelper();

    private static Map<Long, HashSet<String>> userIndexBanquets = new ConcurrentHashMap<>();

    //自动回宴线程池
    private static ThreadTaskManger autoJoinBanquetThreadPool;

    public static CrossBanquetMember getBanquetMember(String banquetId, long userId) {
        return crossBanquetMemberMap.get(banquetId).get(userId);
    }

    public static List<CrossBanquetData> getUserBanquetDataList(long userId) {
        List<CrossBanquetData> banquetList = new ArrayList<>();
        if (userIndexBanquets.containsKey(userId)) {
            for (String banquetId : new ArrayList<>(userIndexBanquets.get(userId))) {
                CrossBanquetData data = userCrossBanquetDataMap.get(banquetId);
                if (data != null) {
                    banquetList.add(data);
                }
            }
        }
        return banquetList;
    }

    public static CrossBanquetData getUserBanquet(long userId) {
        List<CrossBanquetData> userCrossBanquetDataList = getUserBanquetDataList(userId);
        for (CrossBanquetData data : userCrossBanquetDataList) {
            if (!isBanquetOver(data.getBanquetId()) && data.getUserId() == userId && CrossPartyMgr.isBanquetType(data.getType(), eBanquetType.CrossUserBanquet.getValue())) {
                return data;
            }
        }
        return null;
    }

    public static boolean isSelfJoin(long userId, String banquetId) {
        if (userCrossBanquetDataMap.containsKey(banquetId) && crossBanquetMemberMap.get(banquetId).containsKey(userId)) {
            return true;
        }
        return false;
    }


    @Override
    public boolean reloadData() {
        userCrossBanquetDataMap = CrossBanquetBussiness.getUserCrossBanquetMap();

        for (CrossBanquetData banquetData : userCrossBanquetDataMap.values()) {
            if (!userIndexBanquets.containsKey(banquetData.getUserId())) {
                userIndexBanquets.put(banquetData.getUserId(), new HashSet<>());
            }
            synchronized (userIndexBanquets.get(banquetData.getUserId())) {
                userIndexBanquets.get(banquetData.getUserId()).add(banquetData.getBanquetId());
            }
        }

        initCrossBanquetMember();
        crossBanquetRecordMap = CrossBanquetBussiness.getCrossBanquetRecordMap(System.currentTimeMillis() - RECORD_EXPIRE_TIME);
        initLockMap();

        //初始化自动回宴线程池，开1个线程池，线程数量2个
        if(null == autoJoinBanquetThreadPool) {
            autoJoinBanquetThreadPool = new ThreadTaskManger(1, "autoJoinBanquetThreadPool", 2);
        }
        return true;
    }

    public static List<CrossBanquetRecord> getBanquetRecordList(int serverId) {
        List<CrossBanquetRecord> recordList = new ArrayList<>(crossBanquetRecordMap.values());
        recordList.sort(new RecordSort());
        Map<String, CrossBanquetRecord> typeRecordTypeMap = new ConcurrentHashMap<>();
        int count = 0;
        long beginTime = System.currentTimeMillis() - RECORD_EXPIRE_TIME;
        for (CrossBanquetRecord record : recordList) {
            if(record.getOpenTime() < beginTime){
                continue;
            }
            if (record.getRecordObjcet().inServerList(serverId)) {
                typeRecordTypeMap.put(record.getBanquetId(), record);
                count++;
            }
            if (count >= GameConfig.BANQUET_RECORD_LIST_MAX) {
                break;
            }
        }
        return new ArrayList<>(typeRecordTypeMap.values());
    }

    static class RecordSort implements Comparator<CrossBanquetRecord> {
        @Override
        public int compare(CrossBanquetRecord o1, CrossBanquetRecord o2) {
            if (o1.getOpenTime() == o2.getOpenTime()) {
                return 0;
            }
            if (o1.getOpenTime() >= o2.getOpenTime()) {
                return -1;
            }
            return 1;
        }
    }

    public static List<CrossBanquetData> getRunningBanquet() {
        List<CrossBanquetData> banquetList = new ArrayList<>();
        for (CrossBanquetData banquet : userCrossBanquetDataMap.values()) {
            if (!isBanquetOver(banquet.getBanquetId()) && banquet.getStatus() == 1) {
                banquetList.add(banquet);
            }
        }
        return banquetList;
    }

    public static CrossBanquetData getBanquet(String banquetId) {
        return userCrossBanquetDataMap.get(banquetId);
    }

    public static BanquetInfo getBanquetInfo(String banquetId) {
        CrossBanquetData banquetData = userCrossBanquetDataMap.get(banquetId);
        if(banquetData != null){
            return CrossBanquetConfigMgr.getBanquetInfo(banquetData.getType());
        }
        return null;
    }

    //本服盛宴和普通宴会和跨服宴会
    private static boolean canOpenBanquet(long userId) {
        List<CrossBanquetData> banquetList = new ArrayList<>(userCrossBanquetDataMap.values());
        for (CrossBanquetData data : banquetList) {
            if (!isBanquetOver(data.getBanquetId()) && data.getUserId() == userId) {
                return false;
            }
        }
        return true;
    }

    //新增了跨服私人宴会，和跨服盛宴不冲突可以各开一个
    private static boolean canOpenBanquet(long userId, int type) {
        List<CrossBanquetData> banquetList = new ArrayList<>(getUserBanquetDataList(userId));
        for (CrossBanquetData data : banquetList) {
            if (!isBanquetOver(data.getBanquetId()) && data.getUserId() == userId && CrossBanquetConfigMgr.isTheSameType(data.getType(), type)) {
                return false;
            }
        }
        return true;
    }

    public static int checkOpenBanquet(long userId, int type, String serverList) {
        BanquetInfo banquetInfo = CrossBanquetConfigMgr.getBanquetInfo(type);
        if (banquetInfo == null) {
            return GameErrorCode.E_BANQUET_INFO_ERROR;
        }
        if (type != eBanquetInfoType.CrossMogulBirthdayBanquet.getValue() &&!canOpenBanquet(userId, type)) {
            return GameErrorCode.E_BANQUET_ONLY_ONE;
        }
        if (StringUtils.isNullOrEmpty(serverList)) {
            return GameErrorCode.E_BANQUET_INFO_ERROR;
        }
        return 0;
    }

    public static String preOpenBanquet(int serverId, long userId, UserBaseInfo userBaseInfo, int type, String invitationId,
                                        String invitationInfo, String serverList, String giftTypeAccept, boolean autoOpen) {
        CrossUserMgr.updateUserBaseInfo(userId, userBaseInfo);
        BanquetInfo banquetInfo = CrossBanquetConfigMgr.getBanquetInfo(type);
        CrossBanquetData crossBanquetData = new CrossBanquetData();
        crossBanquetData.setBanquetId(UUIDHelper.randomUUID(String.valueOf(userBaseInfo.getServerId())));
        crossBanquetData.setServerId(serverId);
        crossBanquetData.setUserId(userId);
        crossBanquetData.setOpenTime(System.currentTimeMillis());
        crossBanquetData.setOverTime(System.currentTimeMillis() + banquetInfo.getBanquetTime() * 1000);
        if(type == eBanquetInfoType.CrossMogulBirthdayBanquet.getValue()){
            crossBanquetData.setOverTime(DateHelper.getTodayZeroTimeStamp() + DateHelper.DAY_MILLIONS);
        }
        crossBanquetData.setSendReward(false);
        crossBanquetData.setType(type);
        crossBanquetData.setPopularity(0);
        crossBanquetData.setIntegral(0);
        crossBanquetData.setUserCount(0);
        crossBanquetData.setUserBaseInfo(userBaseInfo);
        crossBanquetData.setServerListStr(serverList);
        crossBanquetData.setStatus(0);
        crossBanquetData.setAutoOpen(autoOpen?1:0);
        crossBanquetData.setInvitationId(invitationId);
        crossBanquetData.setInvitationInfo(invitationInfo);
        crossBanquetData.setGiftTypeAccept(giftTypeAccept);
        crossBanquetData.setMessage("");
        crossBanquetData.setInsertOption();
        crossBanquetData.setAutoOpen(autoOpen?1:0);

        userCrossBanquetDataMap.put(crossBanquetData.getBanquetId(), crossBanquetData);

        if (!userIndexBanquets.containsKey(crossBanquetData.getUserId())) {
            userIndexBanquets.put(crossBanquetData.getUserId(), new HashSet<>());
        }
        synchronized (userIndexBanquets.get(crossBanquetData.getUserId())) {
            userIndexBanquets.get(crossBanquetData.getUserId()).add(crossBanquetData.getBanquetId());
        }


        crossBanquetMemberMap.put(crossBanquetData.getBanquetId(), new ConcurrentHashMap<>());
        addLockValue(crossBanquetData.getBanquetId());

        return crossBanquetData.getBanquetId();
    }

    public static int openBanquet(String banquetId) {
        CrossBanquetData crossBanquetData = userCrossBanquetDataMap.get(banquetId);
        if (crossBanquetData == null) {
            return GameErrorCode.E_BANQUET_CROSS_OPEN;
        }
        crossBanquetData.setStatus(1);
        crossBanquetMemberMap.put(crossBanquetData.getBanquetId(), new ConcurrentHashMap<>());
        addLockValue(crossBanquetData.getBanquetId());
        return 0;
    }

    //还有个自动赴宴的复制的，有改这里也要改那里
    public static CrossBanquetProto.JoinCrossBanquetResp.Builder joinBanquet(int serverId, long userId, String banquetId, int giftId, int titleAdd,
                                                                             int patronsSkillAdd, UserBaseInfo userBaseInfo, long endTime, int giftAcceptState,int autoJoinState,int acId) {
        CrossBanquetProto.JoinCrossBanquetResp.Builder respMsg = CrossBanquetProto.JoinCrossBanquetResp.newBuilder();
        respMsg.setRet(0);
        respMsg.setGiftId(giftId);
        respMsg.setBanquetId(banquetId);
        respMsg.setPos(0);
        Object lockObject = getLockValue(banquetId);
        if (lockObject == null) {
            return respMsg.setRet(GameErrorCode.E_GAME_ERROR);
        }
        CrossBanquetData crossBanquetData;
        crossBanquetData = userCrossBanquetDataMap.get(banquetId);
        if(null == crossBanquetData){
            return respMsg.setRet(GameErrorCode.E_BANQUET_IS_OVER);
        }
        if (!crossBanquetData.inServerList(serverId)) {
            return respMsg.setRet(GameErrorCode.E_BANQUET_CROSS_JOIN_SERVER);
        }
        Map<Long, CrossBanquetMember> memberMap = crossBanquetMemberMap.get(banquetId);
        BanquetInfo banquetInfo = CrossBanquetConfigMgr.getBanquetInfo(crossBanquetData.getType());
        BanquetGiftInfo banquetGiftInfo = CrossBanquetConfigMgr.getBanquetGiftInfo(crossBanquetData.getType(), giftId);
        if (banquetInfo == null) {
            return respMsg.setRet(GameErrorCode.E_BANQUET_INFO_ERROR);
        }
        if (banquetGiftInfo == null) {
            return respMsg.setRet(GameErrorCode.E_BANQUET_GIFT_ERROR);
        }
        if (memberMap.containsKey(userId)) {
            return respMsg.setRet(GameErrorCode.E_BANQUET_HAS_JOIN);
        }
        if (!"0".equals(banquetGiftInfo.getJoinConsume()) && CrossBanquetConfigMgr.isCrossBanquet(crossBanquetData.getType())) {
            return respMsg.setRet(GameErrorCode.E_BANQUET_GIFT_ERROR);
        }
        if (memberMap.size() >= banquetInfo.getSeat() && banquetInfo.getSeat() != 0) {
            return respMsg.setRet(GameErrorCode.E_BANQUET_MAX_SEAT);
        }

        if (!crossBanquetData.isGiftIdAccept(giftId)){
            return respMsg.setRet(GameErrorCode.E_BANQUET_JOIN_GIFTTYPE_NO_ENOUGH).setGiftTypeAccept(crossBanquetData.getGiftTypeAccept());
        } else if(2 == giftAcceptState){
            return respMsg.setRet(GameErrorCode.E_BANQUET_JOIN_GIFTTYPE_NO_ENOUGH).setGiftTypeAccept(crossBanquetData.getGiftTypeAccept());
        }
        BigDecimal popularity = BigDecimal.ZERO;
        BigDecimal integral = BigDecimal.ZERO;
        if (!"0".equals(banquetGiftInfo.getJoinScore())) {
            //头衔加成
            Property joinScore = PropertyHelper.parseStringToProperty(banquetGiftInfo.getJoinScore());
            popularity = BigDecimal.valueOf(joinScore.getCountByGoodsId(GameConfig.BANQUET_POPULARITY).longValue());
            integral = BigDecimal.valueOf(joinScore.getCountByGoodsId(GameConfig.BANQUET_INTEGRAL).longValue());
            int titleAddTemp = 0;
            if (banquetInfo.isTitleAdd()) {
                titleAddTemp = titleAdd;
            }
            popularity = popularity.multiply((BigDecimal.valueOf(1000 + titleAddTemp))).divide(BigDecimal.valueOf(1000));
            integral = integral.multiply((BigDecimal.valueOf(1000 + titleAddTemp))).divide(BigDecimal.valueOf(1000));

            //门客技能不加成，防止某天又要加成
            if (CrossBanquetConfigMgr.isCrossUserBanquet(banquetInfo.getId())) {
                //门客技能加成
                popularity = popularity.
                        multiply(BigDecimal.valueOf(1000).add(BigDecimal.valueOf(patronsSkillAdd))).
                        divide(BigDecimal.valueOf(1000));
            }

            integral = integral.divide(BigDecimal.valueOf(1), 0, BigDecimal.ROUND_UP);
            popularity = popularity.divide(BigDecimal.valueOf(1), 0, BigDecimal.ROUND_UP);
        }
        CrossBanquetMember crossBanquetMember = null;
        synchronized (lockObject) {
            memberMap = crossBanquetMemberMap.get(banquetId);
            if (memberMap.containsKey(userId)) {
                return respMsg.setRet(GameErrorCode.E_BANQUET_HAS_JOIN);
            }
            if (memberMap.size() >= banquetInfo.getSeat() && banquetInfo.getSeat() != 0) {
                return respMsg.setRet(GameErrorCode.E_BANQUET_MAX_SEAT);
            }

            if (!crossBanquetData.isGiftIdAccept(giftId)){
                return respMsg.setRet(GameErrorCode.E_BANQUET_JOIN_GIFTTYPE_NO_ENOUGH).setGiftTypeAccept(crossBanquetData.getGiftTypeAccept());
            } else if(2 == giftAcceptState){
                return respMsg.setRet(GameErrorCode.E_BANQUET_JOIN_GIFTTYPE_NO_ENOUGH).setGiftTypeAccept(crossBanquetData.getGiftTypeAccept());
            }

            CrossBanquetAutoData autoData = CrossBanquetAutoMgr.getUserData(0,crossBanquetData.getUserId());
            if(autoData != null && autoData.getItemMap().getOrDefault(banquetGiftInfo.getJoinConsume(),0) <= 0){
                if(autoJoinState == 1){
                    return respMsg.setRet(GameErrorCode.E_BANQUET_JOIN_AUTO_STATE_CHANGE).setAutoJoinInfo(CrossBanquetAutoMgr.getUserAutoJoinInfo(acId,crossBanquetData.getUserId()));
                }
            }

            crossBanquetMember = new CrossBanquetMember();
            crossBanquetMember.setBanquetId(banquetId);
            crossBanquetMember.setUserId(userId);
            crossBanquetMember.setGiftId(giftId);
            crossBanquetMember.setRobot(false);
            crossBanquetMember.setRobotProcessId(0);
            crossBanquetMember.setRobotId(0);
            crossBanquetMember.setPos(memberMap.size() + 1);
            crossBanquetMember.setPopularity(0);
            crossBanquetMember.setIntegral(0);
            crossBanquetMember.setUserBaseInfo(userBaseInfo);
            crossBanquetMember.setJoinTime(System.currentTimeMillis());
            setMemberUserInfo(crossBanquetMember);
            respMsg.setPos(crossBanquetMember.getPos());
            if (!"0".equals(banquetGiftInfo.getJoinScore())) {
                crossBanquetMember.setPopularity(popularity.longValue());
                crossBanquetMember.setIntegral(integral.longValue());
                //宴会加上人气和积分(跨服盛宴是不会加的，结算的时候给开宴会的算，跨服私人宴会会直接加上),约定好的跨服会配0,不知道为什么注释掉了
                if (CrossBanquetConfigMgr.isCrossUserBanquet(banquetInfo.getId()) || CrossBanquetConfigMgr.isMogulBirthdayBanquet(banquetInfo.getId())) {
                    crossBanquetData.setPopularity(crossBanquetData.getPopularity() + popularity.longValue());
                    crossBanquetData.setIntegral(crossBanquetData.getIntegral() + integral.longValue());
                }
            }
            crossBanquetMember.setInsertOption();
            crossBanquetMemberMap.get(banquetId).put(crossBanquetMember.getUserId(), crossBanquetMember);

            crossBanquetData.setUserCount(memberMap.size());

            if (CrossBanquetConfigMgr.isCrossUserBanquet(crossBanquetData.getType())) {
                CrossPartyMgr.addPartyRelationship(crossBanquetData.getUserId(), userId, userBaseInfo, crossBanquetData.getUserBaseInfo(), crossBanquetData.getType(), endTime);
            }
            //人满了直接发满员幸运奖励
            if (memberMap.size() == banquetInfo.getSeat()) {
                sendLuckUserReward(banquetInfo, crossBanquetData, memberMap);
            }
//            try{
//                joinAutoBack(crossBanquetData,userId,giftId,endTime,acId);
//            }catch (Exception e){
//                getLogger().error("autoJoinBanquet error:",e);
//            }
        }

        syncBanquetServer(crossBanquetData.getBanquetId());
        syncBanquetMemberServer(crossBanquetData, crossBanquetMember);
        //自动回宴异步处理
        autoJoinBanquetThreadPool.addTask(0, new AutoJoinBanquetBackThreadTask(crossBanquetData, userId, giftId, endTime, acId));
        return respMsg;
    }


    public static void joinAutoBack(CrossBanquetData userBanquetData,long userId,int giftId,long endTime,int acId){
        BanquetInfo banquetInfo = CrossBanquetConfigMgr.getBanquetInfo(userBanquetData.getType());
        //只有宴会冲榜能开的那两个支持自动赴宴
        if(!CrossBanquetConfigMgr.isCrossUserBanquet(banquetInfo.getId())){
            return;
        }
        CrossBanquetAutoData autoData = CrossBanquetAutoMgr.getUserData(0,userBanquetData.getUserId());
        if(autoData == null){
            return;
        }
        BanquetGiftInfo giftInfo = CrossBanquetConfigMgr.getBanquetGiftInfo(giftId);
        Property ap = PropertyHelper.parseStringToProperty(giftInfo.getJoinConsume());
        Map<String, Integer> itemMap = autoData.getItemMap();
        if(itemMap.containsKey(giftInfo.getJoinConsume()) && itemMap.get(giftInfo.getJoinConsume()) > 0){
            Map<Integer,BanquetGiftInfo> giftInfoMap = CrossBanquetConfigMgr.getBanquetGiftInfoSameConsume(giftId);
            List<CrossBanquetData> banquetDataList = getUserBanquetDataList(userId);
            for(CrossBanquetData banquetData : banquetDataList){
                if(!isBanquetOver(banquetData.getBanquetId()) && crossBanquetMemberMap.get(banquetData.getBanquetId()) != null && !crossBanquetMemberMap.get(banquetData.getBanquetId()).containsKey(userBanquetData.getUserId())){
                    BanquetInfo banquetInfoMy = CrossBanquetConfigMgr.getBanquetInfo(banquetData.getType());
                    if(!CrossBanquetConfigMgr.isCrossUserBanquet(banquetInfoMy.getId())){
                        continue;
                    }
                    for(BanquetGiftInfo joinGift : giftInfoMap.values()){
                        Property bp = PropertyHelper.parseStringToProperty(joinGift.getJoinConsume());
                        if(PropertyHelper.isTheSameGood(ap,bp)){
                            UserBaseInfo joinUserInfo = CrossUserMgr.getUserBaseInfo(userBanquetData.getUserId());
                            if(joinUserInfo == null){
                                return;
                            }
                            BanquetGiftInfo banquetGiftInfo = CrossBanquetConfigMgr.getBanquetGiftInfo(banquetData.getType(), joinGift.getId());
                            if(banquetGiftInfo == null){
                                //道具不对，下一个道具
                                continue;
                            }
                            boolean success = joinBanquetAuto((int)joinUserInfo.getServerId(),userBanquetData.getUserId(),banquetData.getBanquetId(),joinGift.getId(),
                                    autoData.getTitleAdd(),autoData.getSkillAdd(),joinUserInfo,endTime,acId);
                            if(success){
                                itemMap.put(giftInfo.getJoinConsume(),itemMap.get(giftInfo.getJoinConsume()) - 1);
                                autoData.setItemMap(itemMap);
                                Map<Integer, Integer> joinTimesMap = autoData.getJoinTimesMap();
                                int rewardIndex = joinGift.getId() % 10;//只能这样了0是1和2是三种礼
                                for(int goodId : bp.getGoods().keySet()){
                                    if(goodId == GameConfig.GAME_MONEY_INGOTS){
                                        autoData.setIngots(autoData.getIngots() + bp.getGoods().get(goodId).longValue());
                                    }
                                }
                                joinTimesMap.put(rewardIndex,joinTimesMap.getOrDefault(rewardIndex,0) + 1);
                                CrossBanquetAutoMgr.syncUserData(autoData.getUserId(),autoData.getServerId(),autoData.getActivityId());
                            }
                            return;
                        }
                    }
                }
            }
        }
    }

    private static boolean joinBanquetAuto(int serverId, long userId, String banquetId, int giftId, int titleAdd,
                                        int patronsSkillAdd, UserBaseInfo userBaseInfo, long endTime,int acId){
        Object lockObject = getLockValue(banquetId);
        if (lockObject == null) {
            getLogger().info("自动回宴会找不到锁,玩家{}加入宴会{}的时候",banquetId,userId);
            return false;
        }
        synchronized (lockObject) {
            CrossBanquetData crossBanquetData = userCrossBanquetDataMap.get(banquetId);
            if(null == crossBanquetData){
                getLogger().info("自动回宴会找不到宴会,玩家{}加入宴会{}的时候",banquetId,userId);
                return false;
            }
            if (!crossBanquetData.inServerList(serverId)) {
                getLogger().info("自动回宴会区服不对,玩家{}加入宴会{}的时候",banquetId,userId);
                return false;
            }
            Map<Long, CrossBanquetMember> memberMap = crossBanquetMemberMap.get(banquetId);
            BanquetInfo banquetInfo = CrossBanquetConfigMgr.getBanquetInfo(crossBanquetData.getType());
            BanquetGiftInfo banquetGiftInfo = CrossBanquetConfigMgr.getBanquetGiftInfo(crossBanquetData.getType(), giftId);
            if (banquetInfo == null) {
                getLogger().info("自动回宴会礼物不对,玩家{}加入宴会{}的时候",banquetId,userId);
                return false;
            }
            if (banquetGiftInfo == null) {
                getLogger().info("自动回宴会礼物不对2,玩家{}加入宴会{}的时候",banquetId,userId);
                return false;
            }
            if (memberMap.containsKey(userId)) {
                getLogger().info("自动回宴会已经坐上去了,玩家{}加入宴会{}的时候",banquetId,userId);
                return false;
            }
            if (!"0".equals(banquetGiftInfo.getJoinConsume()) && CrossBanquetConfigMgr.isCrossBanquet(crossBanquetData.getType())) {
                getLogger().info("自动回宴会随礼不存在或者不匹配,玩家{}加入宴会{}的时候",banquetId,userId);
                return false;
            }
            if (memberMap.size() >= banquetInfo.getSeat() && banquetInfo.getSeat() != 0) {
                getLogger().info("自动回宴会坐满了,玩家{}加入宴会{}的时候",banquetId,userId);
                return false;
            }

            //只要设置了自动赴宴，就不会拒绝
            if (!crossBanquetData.isGiftIdAccept(giftId)){
                getLogger().info("自动回宴会玩家拒绝了这个礼物的回宴道具{},玩家{}加入宴会{}的时候",giftId,banquetId,userId);
                return false;
            }

            CrossBanquetMember crossBanquetMember = new CrossBanquetMember();
            crossBanquetMember.setBanquetId(banquetId);
            crossBanquetMember.setUserId(userId);
            crossBanquetMember.setGiftId(giftId);
            crossBanquetMember.setRobot(false);
            crossBanquetMember.setRobotProcessId(0);
            crossBanquetMember.setRobotId(0);
            crossBanquetMember.setPos(memberMap.size() + 1);
            crossBanquetMember.setPopularity(0);
            crossBanquetMember.setIntegral(0);
            crossBanquetMember.setUserBaseInfo(userBaseInfo);
            crossBanquetMember.setJoinTime(System.currentTimeMillis());
            setMemberUserInfo(crossBanquetMember);
            if (!"0".equals(banquetGiftInfo.getJoinScore())) {
                //头衔加成
                Property joinScore = PropertyHelper.parseStringToProperty(banquetGiftInfo.getJoinScore());
                BigDecimal popularity = BigDecimal.valueOf(joinScore.getCountByGoodsId(GameConfig.BANQUET_POPULARITY).longValue());
                BigDecimal integral = BigDecimal.valueOf(joinScore.getCountByGoodsId(GameConfig.BANQUET_INTEGRAL).longValue());
                int titleAddTemp = 0;
                if (banquetInfo.isTitleAdd()) {
                    titleAddTemp = titleAdd;
                }
                popularity = popularity.multiply((BigDecimal.valueOf(1000 + titleAddTemp))).divide(BigDecimal.valueOf(1000));
                integral = integral.multiply((BigDecimal.valueOf(1000 + titleAddTemp))).divide(BigDecimal.valueOf(1000));

                //门客技能不加成，防止某天又要加成
                if (CrossBanquetConfigMgr.isCrossUserBanquet(banquetInfo.getId())) {
                    //门客技能加成
                    popularity = popularity.
                            multiply(BigDecimal.valueOf(1000).add(BigDecimal.valueOf(patronsSkillAdd))).
                            divide(BigDecimal.valueOf(1000));
                }

                integral = integral.divide(BigDecimal.valueOf(1), 0, BigDecimal.ROUND_UP);
                popularity = popularity.divide(BigDecimal.valueOf(1), 0, BigDecimal.ROUND_UP);

                crossBanquetMember.setPopularity(popularity.longValue());
                crossBanquetMember.setIntegral(integral.longValue());
                //宴会加上人气和积分(跨服盛宴是不会加的，结算的时候给开宴会的算，跨服私人宴会会直接加上),约定好的跨服会配0,不知道为什么注释掉了
                if (CrossBanquetConfigMgr.isCrossUserBanquet(banquetInfo.getId()) || CrossBanquetConfigMgr.isMogulBirthdayBanquet(banquetInfo.getId())) {
                    crossBanquetData.setPopularity(crossBanquetData.getPopularity() + popularity.longValue());
                    crossBanquetData.setIntegral(crossBanquetData.getIntegral() + integral.longValue());
                }
            }
            crossBanquetMember.setInsertOption();
            crossBanquetMemberMap.get(banquetId).put(crossBanquetMember.getUserId(), crossBanquetMember);

            crossBanquetData.setUserCount(memberMap.size());

            syncBanquetServer(crossBanquetData.getBanquetId());
            syncBanquetMemberServer(crossBanquetData, crossBanquetMember);

            if (CrossBanquetConfigMgr.isCrossUserBanquet(crossBanquetData.getType())) {
                CrossPartyMgr.addPartyRelationship(crossBanquetData.getUserId(), userId, userBaseInfo, crossBanquetData.getUserBaseInfo(), crossBanquetData.getType(), endTime);
            }
            //人满了直接发满员幸运奖励
            if (memberMap.size() == banquetInfo.getSeat()) {
                sendLuckUserReward(banquetInfo, crossBanquetData, memberMap);
            }
            CrossBanquetAutoData autoData = CrossBanquetAutoMgr.getUserData(0,userId);
            //能自动回宴不会没有数据
            if(autoData == null){
                getLogger().error("自动回宴，没有找到玩家的活动数据{}",userId);
                autoData = CrossBanquetAutoMgr.initUserData(acId,userId);
            }
            CrossBanquetAutoJoinLog log = new CrossBanquetAutoJoinLog();
            log.setActivityId(autoData.getActivityId());
            log.setUserId(userId);
            log.setBanquetUserId(crossBanquetData.getUserId());
            log.setBanquetId(crossBanquetData.getBanquetId());
            log.setOpenItemId(banquetInfo.getId());
            log.setJoinItemId(giftId);
            log.setIntegral(crossBanquetMember.getIntegral());
            log.setPopularity(crossBanquetMember.getPopularity());
            log.setTime(System.currentTimeMillis());
            log.setDealReward(true);
            log.setInsertOption();
            synchronized (autoData){
                autoData.setAllIntegral(autoData.getAllIntegral() + log.getIntegral());
                autoData.setAllPopularity(autoData.getAllPopularity() + log.getPopularity());
                autoData.setJoinTimes(autoData.getJoinTimes() + 1);
                autoData.addJoinLog(log,CrossBanquetAutoMgr.getLogLimitCount());
            }
        }
        return true;
    }

    private static void sendLuckUserReward(BanquetInfo banquetInfo, CrossBanquetData crossBanquetData, Map<Long, CrossBanquetMember> memberMap) {
        if (!"0".equals(banquetInfo.getLockReward())) {
            CrossBanquetMember memberInfo = getLuckMember(memberMap);
            if (memberInfo == null) {
                return;
            }
            CrossBanquetProto.SendCrossUserBanquetLuckUserMsg.Builder reqMsg = CrossBanquetProto.SendCrossUserBanquetLuckUserMsg.newBuilder();
            reqMsg.setBanquetId(crossBanquetData.getBanquetId());
            reqMsg.setUserId(memberInfo.getUserId());
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_BANQUET_CROSS_USER_LUCK, reqMsg);
            MessageHelper.sendPacket(memberInfo.getUserBaseInfo().getServerId(), memberInfo.getUserId(), pbMsg);
        }
    }

    //获取满座幸运者
    private static CrossBanquetMember getLuckMember(Map<Long, CrossBanquetMember> memberMap) {
        Map<Long, CrossBanquetMember> userMap = new ConcurrentHashMap<>();
        long i = 1;
        for (CrossBanquetMember member : memberMap.values()) {
            if (!member.isRobot()) {
                userMap.put(i++, member);
            }
        }
        long randomLuckPos = random.next(1, userMap.size() + 1);
        return userMap.get(randomLuckPos);
    }

    public static void addBanquetRecord(CrossBanquetData crossBanquetData) {
        CrossBanquetRecord crossBanquetRecord = new CrossBanquetRecord();
        crossBanquetRecord.setBanquetId(crossBanquetData.getBanquetId());
        crossBanquetRecord.setType(crossBanquetData.getType());
        crossBanquetRecord.setUserId(crossBanquetData.getUserId());
        crossBanquetRecord.setMemberCount(crossBanquetData.getUserCount());
        crossBanquetData.setMemberMap(new ConcurrentHashMap<>());
        crossBanquetRecord.setRecord(JSON.toJSONString(crossBanquetData));
        crossBanquetRecord.setOpenTime(crossBanquetData.getOpenTime());
        crossBanquetRecord.setOverTime(crossBanquetData.getOverTime());
        crossBanquetRecord.setInsertOption();
        crossBanquetRecordMap.put(crossBanquetRecord.getBanquetId(), crossBanquetRecord);
    }

    //跨服私人宴会记录
    public static void sendBanquetUserRecord(CrossBanquetData crossBanquetData) {
        UserBanquetRecord userBanquetRecord = new UserBanquetRecord();
        userBanquetRecord.setBanquetId(crossBanquetData.getBanquetId());
        userBanquetRecord.setType(crossBanquetData.getType());
        userBanquetRecord.setUserId(crossBanquetData.getUserId());
        crossBanquetData.setMemberMap(crossBanquetMemberMap.get(crossBanquetData.getBanquetId()));
        userBanquetRecord.setRecord(JSON.toJSONString(crossBanquetData));
        userBanquetRecord.setOpenTime(crossBanquetData.getOpenTime());
        userBanquetRecord.setOverTime(crossBanquetData.getOverTime());
        userBanquetRecord.setMemberCount(crossBanquetData.getUserCount());

        CrossBanquetProto.SendCrossUserBanquetRecordMsg.Builder respMsg = CrossBanquetProto.SendCrossUserBanquetRecordMsg.newBuilder();
        respMsg.setBanquetId(userBanquetRecord.getBanquetId());
        respMsg.setType(userBanquetRecord.getType());
        respMsg.setUserId(userBanquetRecord.getUserId());
        respMsg.setRecord(userBanquetRecord.getRecord());
        respMsg.setOpenTime(userBanquetRecord.getOpenTime());
        respMsg.setOverTime(userBanquetRecord.getOverTime());
        respMsg.setMemberCount(userBanquetRecord.getMemberCount());

        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_BANQUET_CROSS_USER_SEND_RECORD, respMsg);
        MessageHelper.sendPacket(crossBanquetData.getServerId(), crossBanquetData.getUserId(), pbMsg);
    }

    //跨服盛宴的结束请求
    public static Map<String, CrossBanquetData> getOverBanquetReward(long userId, int beautiesSkillAdd) {
        Map<String, CrossBanquetData> rewardBanquetMap = new ConcurrentHashMap<>();
        List<CrossBanquetData> banquetList = new ArrayList<>(getUserBanquetDataList(userId));
        for (CrossBanquetData data : banquetList) {
            if (!CrossBanquetConfigMgr.isCrossBanquet(data.getType())) {
                continue;
            }
            if (isBanquetOver(data.getBanquetId()) && data.getUserId() == userId && !data.isSendReward()) {
                rewardBanquetMap.put(data.getBanquetId(), getSelfReward(userId, beautiesSkillAdd, data));
            }
        }
        return rewardBanquetMap;
    }

    //跨服私人宴会的结束
    public static Map<String, CrossBanquetData> getOverBanquetUserReward(long userId, int beautiesSkillAdd) {
        Map<String, CrossBanquetData> rewardBanquetMap = new ConcurrentHashMap<>();
        List<CrossBanquetData> banquetList = new ArrayList<>(getUserBanquetDataList(userId));
        for (CrossBanquetData data : banquetList) {
            if (!CrossBanquetConfigMgr.isCrossUserBanquet(data.getType())) {
                continue;
            }
            if (isBanquetOver(data.getBanquetId()) && data.getUserId() == userId && !data.isSendReward()) {
                rewardBanquetMap.put(data.getBanquetId(), getSelfReward(userId, beautiesSkillAdd, data));
            }
        }
        return rewardBanquetMap;
    }

    //获取自己开的宴会的奖励
    private static CrossBanquetData getSelfReward(long userId, int beautiesSkillAdd, CrossBanquetData banquet) {
        banquet.setSendReward(true);
        BanquetInfo banquetInfo = CrossBanquetConfigMgr.getBanquetInfo(banquet.getType());
        //这个字段其实只有本服私宴才有用到,本服的是参加的人数加起来，跨服的直接就按照人数算加成了
        int addEndEffect = banquetInfo.getEndEffect();
        BigDecimal popularity = BigDecimal.valueOf(banquet.getPopularity());
        BigDecimal integral = BigDecimal.valueOf(banquet.getIntegral());
        //跨服私人宴会要把举办者的奖励乘与一个倍数
        if (CrossBanquetConfigMgr.isCrossUserBanquet(banquet.getType())) {
            popularity = popularity.multiply(BigDecimal.valueOf(GameConfig.BANQUET_USER_CROSS_SPONSOR_MUL));
            integral = integral.multiply(BigDecimal.valueOf(GameConfig.BANQUET_USER_CROSS_SPONSOR_MUL));
        }
        popularity = popularity.multiply((BigDecimal.valueOf(1000 + addEndEffect))).divide(BigDecimal.valueOf(1000));
        integral = integral.multiply((BigDecimal.valueOf(1000))).divide(BigDecimal.valueOf(1000));

        //美女技能不加成，防止哪天再加成
        if (CrossBanquetConfigMgr.isCrossUserBanquet(banquetInfo.getId())) {
            popularity = popularity.
                    multiply(BigDecimal.valueOf(1000).add(BigDecimal.valueOf(beautiesSkillAdd))).
                    divide(BigDecimal.valueOf(1000));
        }
        //奖励中也会配置人气和积分奖励,需要加到宴会中去
        long rewardPopularity = 0;
        long rewardIntegral = 0;
        //宴会结束后的奖励
        if (!"0".equals(banquetInfo.getEndReward())) {
            String endRewardStr = CrossBanquetConfigMgr.getEndReward(banquet.getUserCount(), banquet.getType());
            Property endReward = PropertyHelper.parseStringToProperty(endRewardStr);
            //要把宴会和人气的奖励合并起来合到宴会里面去
            rewardPopularity = endReward.getCountByGoodsId(GameConfig.BANQUET_POPULARITY).longValue();
            rewardIntegral = endReward.getCountByGoodsId(GameConfig.BANQUET_INTEGRAL).longValue();
            endReward.removeProperty(GameConfig.BANQUET_POPULARITY, BigInteger.valueOf(rewardPopularity));
            endReward.removeProperty(GameConfig.BANQUET_INTEGRAL, BigInteger.valueOf(rewardIntegral));
            banquet.setEndReward(PropertyHelper.parsePropertyToString(endReward));
        }

        popularity = popularity.add(BigDecimal.valueOf(rewardPopularity));
        integral = integral.add(BigDecimal.valueOf(rewardIntegral));

        integral = integral.divide(BigDecimal.valueOf(1), 0, BigDecimal.ROUND_UP);
        popularity = popularity.divide(BigDecimal.valueOf(1), 0, BigDecimal.ROUND_UP);

        banquet.setPopularity(popularity.longValue());
        banquet.setIntegral(integral.longValue());

        if (CrossBanquetConfigMgr.isCrossBanquet(banquet.getType())) {
            addBanquetRecord(banquet);
        } else if (CrossBanquetConfigMgr.isCrossUserBanquet(banquet.getType())) {
            sendBanquetUserRecord(banquet);
        }
        syncBanquetServer(banquet.getBanquetId());

        return banquet;
    }

    //开启宴会和加入宴会同步
    public static void syncBanquetServer(String banquetId) {
        CrossBanquetData crossBanquetData = userCrossBanquetDataMap.get(banquetId);
        CrossBanquetProto.SyncCrossBanquetMsg.Builder respMsg = CrossBanquetPb.parseSyncCrossBanquetMsg(crossBanquetData);
        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_BANQUET_CROSS_SYNC, respMsg);
        syncServer(pbMsg, crossBanquetData);
    }

    private static void syncServer(YanQuMessage pbMsg, CrossBanquetData crossBanquetData) {
        if ("0".equals(crossBanquetData.getServerListStr())) {
            int channelId = ConfigHelper.getInt("channelId");
            for (ServerInfo serverInfo : ServerListMgr.getOpenServerList(channelId)) {
                MessageHelper.sendPacket(serverInfo.getServerId(), 0, pbMsg);
            }
        } else {
            List<Integer> serverIdList = crossBanquetData.getServerList();
            for (Integer serverId : serverIdList) {
                MessageHelper.sendPacket(serverId, 0, pbMsg);
            }
        }
    }

    /**
     * 定时1S增量推送跨服盛宴成员信息
     */
    public static void syncBanquetMember() {
        for (Map.Entry<String, List<CrossBanquetMember>> listEntry : crossBanquetMemberSyncMap.entrySet()) {
            String banquetId = listEntry.getKey();
            CrossBanquetData crossBanquetData = userCrossBanquetDataMap.get(banquetId);
            if(crossBanquetData != null){
                List<CrossBanquetMember> list;
                synchronized (listEntry.getValue()){
                    if(listEntry.getValue().size() == 0){
                        continue;
                    }
                    list = new ArrayList<>(listEntry.getValue());
                    listEntry.getValue().clear();
                }
                syncBanquetMemberServer(crossBanquetData, list);
            }
        }
    }

    //同步宴会成员
    public static void syncBanquetMemberServer(CrossBanquetData crossBanquetData, CrossBanquetMember crossBanquetMember) {
        //跨服私人宴会直接同步；
        if(CrossBanquetConfigMgr.isCrossUserBanquet(crossBanquetData.getType())){
            List<CrossBanquetMember> list = new ArrayList<>();
            list.add(crossBanquetMember);
            syncBanquetMemberServer(crossBanquetData, list);
        }else {
            if(!crossBanquetMemberSyncMap.containsKey(crossBanquetData.getBanquetId())){
                synchronized (crossBanquetMemberSyncMap){
                    if(!crossBanquetMemberSyncMap.containsKey(crossBanquetData.getBanquetId())){
                        crossBanquetMemberSyncMap.put(crossBanquetData.getBanquetId(), new ArrayList<>());
                    }
                }
            }
            List list = crossBanquetMemberSyncMap.get(crossBanquetData.getBanquetId());
            synchronized (list){
                list.add(crossBanquetMember);
            }
        }
    }

    public static void syncBanquetMemberServer(CrossBanquetData crossBanquetData, List<CrossBanquetMember> list) {
        CrossBanquetProto.SyncCrossBanquetMemberMsg.Builder respMsg = CrossBanquetProto.SyncCrossBanquetMemberMsg.newBuilder();
        for (CrossBanquetMember member : list) {
            CrossBanquetProto.SyncCrossBanquetMemberTemp.Builder temp = CrossBanquetProto.SyncCrossBanquetMemberTemp.newBuilder();
            temp.setServerId(crossBanquetData.getServerId());
            temp.setUserId(member.getUserId());
            temp.setBanquetId(member.getBanquetId());
            temp.setGiftId(member.getGiftId());
            temp.setPopularity(member.getPopularity());
            temp.setIntegral(member.getIntegral());
            temp.setPos(member.getPos());
            temp.setRobot(member.isRobot());
            temp.setRobotProcessId(member.getRobotProcessId());
            temp.setRobotId(member.getRobotId());
            PlayerProto.PlayerBaseTempMsg.Builder baseMsg = PlayerBasePb.parsePlayerBaseTempMsg(member.getUserBaseInfo());
            temp.setUserBaseInfo(baseMsg);
            temp.setAllIntegral(member.getIntegral());
            temp.setAllPopularity(member.getPopularity());
            respMsg.addMemberList(temp);
        }
        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_BANQUET_CROSS_MEMBER_SYNC, respMsg);
        syncServer(pbMsg, crossBanquetData);
    }

    public static boolean isBanquetOver(String banquetId) {
        CrossBanquetData banquet = userCrossBanquetDataMap.get(banquetId);
        if (banquet == null) {
            return true;
        }
        if (banquet.getOverTime() < System.currentTimeMillis()) {
            return true;
        }
        BanquetInfo banquetInfo = CrossBanquetConfigMgr.getBanquetInfo(banquet.getType());
        if (banquetInfo == null) {
            return true;
        }
        if (banquetInfo.getSeat() != 0 && banquet.getUserCount() >= banquetInfo.getSeat()) {
            return true;
        }
        return false;
    }

    private static void initCrossBanquetMember() {
        Map<String, Map<Long, CrossBanquetMember>> userBanquetMemberMap = CrossBanquetBussiness.getAllCrossBanquetMemberMap();
        for (CrossBanquetData data : userCrossBanquetDataMap.values()) {
            //如果是跨服私人宴会要把人放上去，生成记录时候要用
            if (!CrossBanquetConfigMgr.isCrossUserBanquet(data.getType()) && isBanquetOver(data.getBanquetId())) {
                continue;
            }
//            Map<Long, CrossBanquetMember> userMap = CrossBanquetBussiness.getCrossBanquetMemberMap(data.getBanquetId());
            Map<Long, CrossBanquetMember> userMap = userBanquetMemberMap.get(data.getBanquetId());
            if (userMap == null) userMap = new ConcurrentHashMap<>();
            for (CrossBanquetMember crossBanquetMember : userMap.values()) {
                setMemberUserInfo(crossBanquetMember);
            }
            crossBanquetMemberMap.put(data.getBanquetId(), userMap);
            //如果是跨服私人宴会要把人放上去，生成记录时候要用
            if (CrossBanquetConfigMgr.isCrossUserBanquet(data.getType())) {
                data.setMemberMap(userMap);
            }
        }
    }


    //机器人加入宴会用机器人测试用
    private static void robotsJoinBanquetTemp(CrossBanquetData banquetData) {
        robotsJoinBanquet(banquetData.getUserCount() + 1, banquetData);
    }

    private static void robotsJoinBanquet(int processId, CrossBanquetData banquetData) {
        Object lockObj = getLockValue(banquetData.getBanquetId());
        if (lockObj != null) {
            synchronized (lockObj) {
                BanquetInfo banquetInfo = CrossBanquetConfigMgr.getBanquetInfo(banquetData.getType());
                if (banquetInfo == null) {
                    return;
                }
                if ("0".equals(banquetInfo.getRobots())) {
                    return;
                }
                List<Integer> robotList = StringUtils.stringToIntegerList(banquetInfo.getRobots(), "=");
                BanquetGiftInfo banquetGiftInfo = CrossBanquetConfigMgr.getBanquetGiftInfo(banquetData.getType(), robotList.get(1));
                if (banquetGiftInfo == null) {
                    return;
                }
                if (banquetData.getUserCount() >= banquetInfo.getSeat() && banquetInfo.getSeat() != 0) {
                    return;
                }
                Map<Long, CrossBanquetMember> memberMap = crossBanquetMemberMap.get(banquetData.getBanquetId());
                CrossBanquetMember banquetMember = new CrossBanquetMember();
                banquetMember.setBanquetId(banquetData.getBanquetId());
                banquetMember.setUserId(processId);
                banquetMember.setGiftId(robotList.get(1));
                banquetMember.setRobot(true);
                banquetMember.setRobotProcessId(processId);
                banquetMember.setRobotId(robotList.get(0));
                banquetMember.setPos(memberMap.size() + 1);
                banquetMember.setPopularity(0);
                banquetMember.setIntegral(0);
                banquetMember.setUserBaseInfo(initRobotUserInfo());
                banquetMember.setJoinTime(System.currentTimeMillis());
                setMemberUserInfo(banquetMember);
                if (!"0".equals(banquetGiftInfo.getJoinScore())) {
                    //随礼的奖励值加上头衔加成千分比
                    Property joinScore = PropertyHelper.parseStringToProperty(banquetGiftInfo.getJoinScore());
                    long popularity = joinScore.getCountByGoodsId(GameConfig.BANQUET_POPULARITY).longValue();
                    long integral = joinScore.getCountByGoodsId(GameConfig.BANQUET_INTEGRAL).longValue();
                    banquetMember.setPopularity(popularity);
                    banquetMember.setIntegral(integral);

                    if (CrossBanquetConfigMgr.isCrossUserBanquet(banquetData.getType())) {
                        //宴会加上人气和积分
                        banquetData.setPopularity(banquetData.getPopularity() + popularity);
                        banquetData.setIntegral(banquetData.getIntegral() + integral);
                    }

                }
                banquetMember.setInsertOption();
                memberMap.put(banquetMember.getUserId(), banquetMember);

                banquetData.setUserCount(memberMap.size());

                //人满了直接发满员幸运奖励
                if (memberMap.size() == banquetInfo.getSeat()) {
                    sendLuckUserReward(banquetInfo, banquetData, memberMap);
                }
                syncBanquetServer(banquetData.getBanquetId());
                syncBanquetMemberServer(banquetData, banquetMember);
            }
        }
    }

    public static UserBaseInfo initRobotUserInfo() {
        UserBaseInfo userBaseInfo = new UserBaseInfo();
        userBaseInfo.setUserAliasId(0);
        userBaseInfo.setNickName("");
        userBaseInfo.setTitleId(0);
        userBaseInfo.setDecoration("");
        userBaseInfo.setUnionAliasId(0);
        userBaseInfo.setUnionUid("");
        userBaseInfo.setUnionName("");
        userBaseInfo.setVipExp(0);
        userBaseInfo.setSex(0);
        userBaseInfo.setEarnSpeed(BigInteger.ZERO);
        userBaseInfo.setRegisterTime(0);
        userBaseInfo.setServerId(0);
        userBaseInfo.setWorld("");
        userBaseInfo.setContinent("");
        userBaseInfo.setCountry("");
        userBaseInfo.setProvince("");
        userBaseInfo.setCity("");
        userBaseInfo.setLastLoginTime(0);
        userBaseInfo.setHideVipAndAddress(0);
        return userBaseInfo;
    }

    public static void robotsJoin() {
        List<CrossBanquetData> banquetList = new ArrayList<>(userCrossBanquetDataMap.values());
        for (CrossBanquetData data : banquetList) {
            Object object = getLockValue(data.getBanquetId());
            if (object != null) {
                synchronized (object) {
                    if (CrossBanquetConfigMgr.isCrossUserBanquet(data.getType()) && !isBanquetOver(data.getBanquetId())) {
                        int processId = getRobotsConditionProcessId(data);
                        if (processId != 0) {
                            robotsJoinBanquet(processId, data);
                        }
                    }
                    if (!isBanquetOver(data.getBanquetId()) && CrossBanquetConfigMgr.isCrossBanquet(data.getType())) {
                        /*int addCount = 100;
                        for(int i=0;i<addCount;i++){
                            robotsJoinBanquetTemp(data);
                        }*/
                    }
                }
            }
        }
    }

    //获取是否要触发机器人
    private static int getRobotsConditionProcessId(CrossBanquetData userBanquetData) {
        BanquetInfo banquetInfo = CrossBanquetConfigMgr.getBanquetInfo(userBanquetData.getType());
        Map<Integer, List<Integer>> processMap = CrossBanquetConfigMgr.getCrossRobotCondition();
        Map<Long, CrossBanquetMember> memberMap = crossBanquetMemberMap.get(userBanquetData.getBanquetId());
        for (Integer processId : processMap.keySet()) {
            //是否机器人
            boolean robotFlag = false;
            List<Integer> processList = processMap.get(processId);
            long timePass = BigInteger.valueOf(userBanquetData.getOverTime() - userBanquetData.getOpenTime()).multiply(BigInteger.valueOf(processList.get(0))).divide(BigInteger.valueOf(100)).longValue();
            long timeProcess = timePass + userBanquetData.getOpenTime();
            if (System.currentTimeMillis() < timeProcess) {
                continue;
            }
            long seatPass = BigDecimal.valueOf(banquetInfo.getSeat()).multiply(BigDecimal.valueOf(processList.get(1))).divide(BigDecimal.valueOf(100), 0, BigDecimal.ROUND_UP).longValue();
            if (memberMap.size() >= seatPass) {
                continue;
            }
            for (CrossBanquetMember member : memberMap.values()) {
                if (member.isRobot() && processId == member.getRobotProcessId()) {
                    robotFlag = true;
                    break;
                }
            }
            if (!robotFlag) {
                return processId;
            }
        }
        return 0;
    }

    private static void setMemberUserInfo(CrossBanquetMember userBanquetMember) {
        UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userBanquetMember.getUserId());
        if (userBaseInfo != null) {
            userBanquetMember.setUserBaseInfo(userBaseInfo);
        } else {
            UserBaseInfo userBaseInfo1 = userBanquetMember.getUserBaseInfo();
            CrossUserMgr.updateUserBaseInfo(userBanquetMember.getUserId(), userBaseInfo1);
        }
    }

    @Override
    public boolean init() throws Exception {
        return reload();
    }

    @Override
    public boolean reloadConfig() throws Exception {
        return true;
    }

    public static void removeOverTimeBanquet() {
        Set<String> needRemoveSet = new HashSet<>();
        for (CrossBanquetData info : userCrossBanquetDataMap.values()) {
            //大于3小时的移除掉的结束活动(时间到了且已经领奖了)
            if (System.currentTimeMillis() - info.getOverTime() > 1 * 60 * 60 * 1000 && info.getOp() == DataStatus.None && info.isSendReward()) {
                needRemoveSet.add(info.getBanquetId());
            }
            //大于十分钟没有开启成功的移除掉，要和数据库拉取的一样时间，不然可能会出问题
            if (System.currentTimeMillis() - info.getOpenTime() > 10 * 60 * 1000 && info.getStatus() == 0) {
                needRemoveSet.add(info.getBanquetId());
            }
        }
        for (String banquetId : needRemoveSet) {

            try {
                CrossBanquetData banquetData = userCrossBanquetDataMap.get(banquetId);
                if (banquetData != null) {
                    if (userIndexBanquets.containsKey(banquetData.getUserId())) {
                        synchronized (userIndexBanquets.get(banquetData.getUserId())) {
                            userIndexBanquets.get(banquetData.getUserId()).remove(banquetId);
                        }
                    }
                }
            } catch (Exception ex) {
                getLogger().error(ex);
            }

            userCrossBanquetDataMap.remove(banquetId);
            crossBanquetMemberMap.remove(banquetId);
        }

        Set<String> needRemoveRecordSet = new HashSet<>();
        long beginTime = System.currentTimeMillis() - RECORD_EXPIRE_TIME;
        for (CrossBanquetRecord crossBanquetRecord : crossBanquetRecordMap.values()) {
            if(crossBanquetRecord.getOpenTime() < beginTime){
                needRemoveRecordSet.add(crossBanquetRecord.getBanquetId());
            }
        }
        for (String banquetId : needRemoveRecordSet) {
            crossBanquetRecordMap.remove(banquetId);
        }
        if (needRemoveRecordSet.size() > 0) {
            getLogger().info("remove expire banquet record size {}", needRemoveRecordSet.size());
        }

    }

    //预开没有成功的，再次向区服发起开启消息
    public static void reStartBanquet() {
        for (CrossBanquetData info : userCrossBanquetDataMap.values()) {
            //预开启成功但是还没开启宴会
            if (info.getStatus() == 0) {
                CrossBanquetProto.PreOpenCrossBanquetResp.Builder respMsg = CrossBanquetProto.PreOpenCrossBanquetResp.newBuilder();
                respMsg.setRet(0);
                respMsg.setType(info.getType());
                respMsg.setInvitationId(info.getInvitationId());
                respMsg.setBanquetId(info.getBanquetId());
                respMsg.setServerListStr(info.getServerListStr());
                respMsg.setGiftTypeAccept(info.getGiftTypeAccept());
                respMsg.setAutoOpen(info.getAutoOpen()== 1);
                YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_BANQUET_CROSS_PRE_OPEN_RESP, respMsg);
                MessageHelper.sendPacket(info.getServerId(), info.getUserId(), pbMsg);
            }
        }
    }

    public boolean save() {
        reStartBanquet();
        removeOverTimeBanquet();
        List<CrossBanquetData> banquetList = new ArrayList<>(userCrossBanquetDataMap.values());
        for (CrossBanquetData info : banquetList) {
            if (info.getOp() == DataStatus.Insert) {
                CrossBanquetBussiness.addCrossBanquet(info);
            } else if (info.getOp() == DataStatus.Update) {
                CrossBanquetBussiness.updateCrossBanquet(info);
            }
        }
        List<Map<Long, CrossBanquetMember>> banquetMemberMap = new ArrayList<>(crossBanquetMemberMap.values());
        for (Map<Long, CrossBanquetMember> userMap : banquetMemberMap) {
            List<CrossBanquetMember> memberList = new ArrayList<>(userMap.values());
            for (CrossBanquetMember userBanquetMember : memberList) {
                setMemberUserInfo(userBanquetMember);
                if (userBanquetMember.getOp() == DataStatus.Update) {
                    CrossBanquetBussiness.updateCrossBanquetMember(userBanquetMember);
                }
            }
        }
        List<CrossBanquetMember> insertList = new ArrayList<>();
        for (Map<Long, CrossBanquetMember> userMap : banquetMemberMap) {
            List<CrossBanquetMember> memberList = new ArrayList<>(userMap.values());
            for (CrossBanquetMember userBanquetMember : memberList) {
                if (userBanquetMember.getOp() == DataStatus.Insert) {
                    insertList.add(userBanquetMember);
                }
            }
        }
        if (insertList.size() > 0) {
            CrossBanquetBussiness.addCrossBanquetMemberList(insertList);
        }

        List<CrossBanquetRecord> banquetRecordList = new ArrayList<>(crossBanquetRecordMap.values());
        for (CrossBanquetRecord data : banquetRecordList) {
            if (data.isInsertOption()) {
                CrossBanquetBussiness.addCrossBanquetRecord(data);
            }
        }
        return true;
    }

    @Override
    public boolean stop() {
        return false;
    }


    private static void initLockMap() {
        lockMap = new HashMap<>();
        for (Map.Entry<String, CrossBanquetData> userCrossBanquetDataInfo : userCrossBanquetDataMap.entrySet()) {
            lockMap.put(userCrossBanquetDataInfo.getKey(), new Object());
        }
    }

    private static void addLockValue(String banquetId) {
        if (!lockMap.containsKey(banquetId)) {
            lockMap.put(banquetId, new Object());
        }
    }

    private static Object getLockValue(String banquetId) {
        if (lockMap.containsKey(banquetId)) {
            return lockMap.get(banquetId);
        }
        return null;
    }

    //清除跨服宴会自动赴宴的设置
    public static boolean updateCrossAutoPartySetting(long serverId,long userId,List<String> consumeList){
        Map<String, CrossBanquetData> map = new ConcurrentHashMap<>(userCrossBanquetDataMap);
        for(CrossBanquetData banquetData : map.values()){
            if(isBanquetOver(banquetData.getBanquetId()) || banquetData.getUserId() != userId){
                continue;
            }
            BanquetInfo banquetInfo = CrossBanquetConfigMgr.getBanquetInfo(banquetData.getType());
            //只有宴会冲榜能开的那两个支持自动赴宴
            if(!CrossBanquetConfigMgr.isCrossUserBanquet(banquetInfo.getId())){
                continue;
            }
            List<Integer> giftIdList = StringUtils.stringToIntegerList(banquetData.getGiftTypeAccept(),"\\|");
            for(String consume : consumeList){
                BanquetGiftInfo giftInfo = CrossBanquetConfigMgr.getBanquetGiftByConsume(banquetInfo,consume);
                if(giftInfo != null && !giftIdList.contains(giftInfo.getId())){
                    giftIdList.add(giftInfo.getId());
                }
            }
            banquetData.setGiftTypeAccept(StringUtils.listToString(giftIdList,"|"));
            BanquetProto.UpdateBanquetSettingCrossRespMsg.Builder resp = BanquetProto.UpdateBanquetSettingCrossRespMsg.newBuilder();
            resp.setType(banquetData.getType());
            resp.setGiftTypeAccept(banquetData.getGiftTypeAccept());
            resp.setBanquetId(banquetData.getBanquetId());
            resp.setMessage(banquetData.getMessage());
            YanQuMessage message = YanQuMessageUtils.buildMessage(GameProtocol.S_BANQUET_CROSS_SETTING_UPDATE, resp);
            MessageHelper.sendPacket(serverId, userId, message);

            syncBanquetServer(banquetData.getBanquetId());
        }
        return true;
    }

    public static boolean updatePartySetting(long serverId, long userId, int type, String giftTypeAccept, String banquetId, String message1) {
        CrossBanquetData userCrossBanquetData = null;
        if (StringUtils.isNullOrEmpty(banquetId)) {
            userCrossBanquetData = getUserBanquet(userId);
        } else {
            userCrossBanquetData = userCrossBanquetDataMap.get(banquetId);
        }

        if (userCrossBanquetData == null) {
            return false;
        }
        if (isBanquetOver(userCrossBanquetData.getBanquetId()))
            return false;
        if (userCrossBanquetData.getType() != type)
            return false;
        userCrossBanquetData.setGiftTypeAccept(giftTypeAccept);
        userCrossBanquetData.setMessage(message1);
        BanquetProto.UpdateBanquetSettingCrossRespMsg.Builder resp = BanquetProto.UpdateBanquetSettingCrossRespMsg.newBuilder();
        resp.setType(type);
        resp.setGiftTypeAccept(giftTypeAccept);
        resp.setBanquetId(userCrossBanquetData.getBanquetId());
        resp.setMessage(message1);
        YanQuMessage message = YanQuMessageUtils.buildMessage(GameProtocol.S_BANQUET_CROSS_SETTING_UPDATE, resp);
        MessageHelper.sendPacket(serverId, userId, message);

        syncBanquetServer(userCrossBanquetData.getBanquetId());

        return true;
    }

}
